/* Copyright  2009
   @Author
   Richard Changde Yin            e-mail yinchangde@hotmail.com

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; version 2 of the License.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

/**
 *@filename:  util.h
 */

#ifndef __UTIL_H__
#define __UTIL_H__

#include <error.h>



#ifdef __cplusplus
extern "C" {
#endif
    void     util_randominit   (struct rand_struct *, uint64_t seed1,
                                uint64_t seed2);
    char *   util_octet2hex    (char *to, const char *str, unsigned int len);

    uint32_t util_escape_string(char *to,const char *from,
                                     uint32_t from_length);
#ifdef __cplusplus
}
#endif

namespace  BackEnd {

class ListNode
{
    ListNode& operator =(const ListNode& );
    ListNode (const ListNode& );
    ListNode (ListNode& );
public:
    void *element         ;
    ListNode *next        ;

    ListNode():element(0),next(0) {}
    ListNode(void* _element):element(_element),next(0){}
}; // End of ListNode

class ListIterator
{
    ListNode *iter;
    ListNode *start;
public:
    ListIterator():iter(0),start(0){}

    ListIterator(ListNode *head):iter(head),start(head) {}

    virtual ListIterator(){}
    inline bool hasElement()
    {
      if (!iter) return false;
      else return true;
    }

    inline void reset()
    {
        iter = start;
    }
    inline void* nextElement()
    {
        if (!iter) return NULL;
        ListNode *node = iter;
        iter = iter ->next;
        return node->element;
    }

    //index start with one, such that 1->first element in list
    inline void* getElement(int index)
    {
        ListNode *localIter = start;
        if (localIter == NULL) return NULL;
        for (int i=0; i <index; i++) {
           localIter = localIter->next;
           if (localIter == NULL) return NULL ;
        }
        return localIter->element;
    }

    inline void* getCurrentElement()
    {
       if (iter == NULL)  return NULL ;
       return iter->element ;
    }
};

class Identifier
{
    Identifier(const Identifier&);
    Identifier& operator= (const Identifier&);
public:
    inline Identifier(){
      bzero(name, IDENTIFIER_LENGTH);
    }

    inline Identifier(const char* _name){
      strcpy(name, _name);
    }
    char name[IDENTIFIER_LENGTH];
};

template <class T> class List
{
    ListNode *head;
    uint32_t totalElements;
public:

    List():head(0),totalElements(0) {}

    inline BackEnd::DbRetVal append(T* elem)
    {
        ListNode*newNode = new ListNode((void*) elem);

        totalElements++;
        //If this is the first node, set it as head
        if (!head) { head = newNode; return OK; }

        ListNode *iter = head;
        while (iter->next) iter = iter->next;
        iter->next = newNode;
        return OK;
    }
    //Warning:Try to avoid using this method while using the iterator.
    //The behavior is undefined. Instead set flag isRemove to yes
    //and call nextElement of iterator.
    inline BackEnd::DbRetVal remove(void *elem)
    {
        if (!head)
          return ER_NotExists;

        ListNode  *iter = head, *prev = head;
        while (iter)
        {
          if (elem ==(void*) iter->element)
          {
            if (iter == head)
            {  head = iter->next;
               totalElements--;
               delete iter;
               return OK;
            }
             prev->next = iter->next;
             delete iter;
             totalElements--;
             return OK;
           }
           prev = iter;
           iter = iter->next;
        }
        return ER_NotFound;
    }

    //index start with one, such that 1->first element in list
    inline void* get(int index)
    {
        ListNode *localIter = head;
        if (!localIter) return (void*)0;
        for (int i=0; i <index-1; i++) {
           localIter = localIter->next;
           if (localIter == NULL) return (void*)0;
        }
        return localIter->element;
    }

    inline bool exists(void *elem)
    {
        ListNode  *iter = head;
        while (iter != NULL)
        {
          if (elem == (void*)iter->element)
          {
            return true;
          }
            iter = iter->next;
        }
        return false;
    }

    inline ListIterator getIterator()
    {
        ListIterator iter(head);
        return iter;
    }
    inline void reset(bool b_removeElement = false)
    {
      if (NULL == head) return;
      ListNode  *iter = head, *prevIter = head;
      while (iter->next != NULL)
      {
        prevIter = iter;
        iter = iter->next;
        if(b_removeElement) delete static_cast<T*>(prevIter->element) ;
          delete prevIter;
      }
      if(b_removeElement) delete static_cast<T*>(iter->element) ;
      delete iter;
      head = NULL ;
      totalElements = 0;
      return;
    }

    inline void removeAll()
    {
      if (!head) return;
      ListNode  *iter = head, *prevIter = head;
      while (iter->next != NULL)
      {
        prevIter = iter;
        iter = iter->next;
        delete prevIter;
      }
      delete iter;
      head = NULL ;
      totalElements = 0;
      return;
    }

    inline void empty()
    {
      reset(true);
    }
    inline uint32_t size()
    {
      if(!head) return (0);
        return totalElements;
    }
};

} // End of namespace
#endif  //__UTIL_H__
